# coding:utf-8
from django.contrib.auth.decorators import login_required, permission_required
from .forms import SubmissionForm, DiscussForm, ProblemSearchForm
from datetime import datetime
from django.shortcuts import render
from django.http import HttpRequest, Http404, HttpResponse, FileResponse
from app.models import *
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
import json
#from judge.tasks import judge_task
import os
from django.db import connection
from django.contrib.auth.models import User, Group
#from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Count


def home(request):
    """Renders the home page."""
    assert isinstance(request, HttpRequest)
    return render(
        request,
        'app/index.html',
        {
            'title': '首页',
        }
    )


def video(request):
    assert isinstance(request, HttpRequest)
    return render(
        request,
        'app/video.html',
        {
            'title': '视频教程',
        }
    )


# 简单的博客，只显示tag、类别、文章列表、文章
def blog(request):
    assert isinstance(request, HttpRequest)
    pagesize = 10
    cdata = request.GET

    stype = 0 if cdata.get('stype') == None else int(cdata.get('stype'))  # 共4种情况, 0 首页 1 文章ID 2 TAG 3 类别
    skey = 0 if cdata.get('skey') == None else int(cdata.get('skey'))  # skey 也是数字
    page = 1 if cdata.get('page') == None else int(cdata.get('page'))  # 1 2 3 4 5

    tags = BlogTag.objects.all()
    categories = BlogCategory.objects.all()

    title = '26中信奥社团'
    # 共4种情况, 0 首页 1 文章ID 2 TAG 3 类别
    # 动态查询的字段
    kwargs = {}
    if stype == 1:
        kwargs['id'] = skey
    elif stype == 2:
        kwargs['tags__id'] = skey
    elif stype == 3:
        kwargs['categories__id'] = skey

    # 应用所有的查询
    count = Blog.objects.filter(**kwargs).count()
    blogs = Blog.objects.filter(**kwargs)[(page - 1) * pagesize: page * pagesize]

    urlextra = request.path_info + '?stype=%s&skey=%s&page=' % (stype, skey)

    if count > 0:
        if stype == 0:
            title = '首页 - ' + title
            stxt = None
        elif stype == 1:
            b = blogs[0]
            title = b.title + ' - ' + title
            stxt = None
        elif stype == 2:
            t = next(x for x in tags if x.id == skey)
            stxt = t.name
            title = t.name + ' - ' + title
        elif stype == 3:
            t = next(x for x in categories if x.id == skey)
            title = t.name + ' - ' + title
            stxt = t.name

    if count > 0 and stype != 1:
        p = Paginator(range(count), pagesize)
        pages = p.page(page)
        islist = True
    else:
        pages = None
        islist = False

    return render(
        request,
        'app/blog.html',
        {
            'categories': categories,
            'tags': tags,
            'title': title,
            'blogs': blogs,
            'islist': islist,  # 是否为列表
            'pages': pages,  # 分页
            'urlextra': urlextra,
            'stype': stype,  # 共4种情况, 0 首页 1 文章ID 2 TAG 3 类别
            'skey': skey,  # id
            'stxt': stxt,  # id
        }
    )


# 查看练习的统计信息、历次作业、习题列表及内容、提交练习并显示结果、提出问题及反馈官吏到BBS应用中
@login_required(login_url='/login/')
def homework(request):  # 全部列出，内容为作业时间，题目，题目链接，题目的完成情况
    assert isinstance(request, HttpRequest)

    # 多对多关系查询，直接使用定义访问如下：user.groups.all()；使用关联查询如下：group.homework_set.all()
    u = request.user
    groups = u.groups.all()

    if len(groups) == 0:
        raise Http404

    group = groups[0]
    hs = group.homework_set.all()
    works = []
    pids = []
    qc = 0;
    qac = 0;
    for h in hs:
        # 可以使用values来返回一下字典，包含指写的列，这样就用返回整个对象了，更省内存
        ps = h.special.problems.values("id", "_id", "title", "submission_number", "accepted_number", "difficulty",
                                       "create_time")
        works.append({'h': h, 'ps': list(ps)})
        for p in ps:
            pids.append(Problem(id=p['id']))

    ss = Submission.objects.filter(user=u, result=JudgeStatus.ACCEPTED, problem__in=pids).values("id", "result",
                                                                                                 "problem_id",
                                                                                                 "create_time")
    sdic = {}
    for s in ss:
        sdic[s["problem_id"]] = s;

    for w in works:
        for p in w['ps']:
            qc += 1
            if p['id'] in sdic:
                qac += 1
                p['submission'] = '完成'
            else:
                p['submission'] = '未完成'

    return render(
        request,
        'app/homework.html',
        {
            'title': '作业列表',
            'works': works,
            'qc': qc,
            'qac': qac,
        }
    )


def listquestion(request):  # 题目列表
    assert isinstance(request, HttpRequest)
    pagesize = 20
    form = ProblemSearchForm(request.GET)
    form.is_valid()
    cdata = form.cleaned_data
    search_type = cdata.get('search_type')  # title id _id
    search_key = cdata.get('search_key')  # key
    tag = 0 if cdata.get('tag') == None else cdata.get('tag')  # tag id
    difficulty = 0 if cdata.get('difficulty') == None else cdata.get('difficulty')  # 1 2 3
    page = 1 if cdata.get('page') == None else cdata.get('page')  # 1 2 3 4 5

    tags = ProblemTag.objects.all()

    # 动态查询的字段
    kwargs = {}

    if search_type != '' and search_key != '':
        kwargs[search_type] = search_key
    if tag > 0:
        kwargs['tags__id'] = tag
    if difficulty > 0:
        kwargs['difficulty'] = str(difficulty)

    # 应用所有的查询
    count = Problem.objects.filter(**kwargs).count()
    problems = Problem.objects.filter(**kwargs)[(page - 1) * pagesize: page * pagesize]

    ps = []
    for p in problems:
        ps.append({'p': p, 'tags': p.tags.all()})

    urlextra = request.path_info + '?search_type=%s&search_key=%s&tag=%d&difficulty=%d&page=' % (
    search_type, search_key, tag, difficulty)

    p = Paginator(range(count), pagesize)
    lines = p.page(page)

    return render(
        request,
        'app/listquestion.html',
        {
            'title': '习题列表',
            'lines': lines,
            'problems': ps,
            'tags': tags,
            'urlextra': urlextra,
        }
    )


@login_required(login_url='/login/')
def downloadcase(request):
    case_id = request.GET['case_id']
    filename = request.GET['filename']
    case_path = '/test_case/'
    file_path = os.path.join(case_path, case_id, filename)
    if os.path.exists(file_path):
        file = open(file_path, 'rb')
        response = FileResponse(file)
        response['Content-Type'] = 'application/octet-stream'
        response['Content-Disposition'] = 'attachment;filename="' + filename + '"'
        return response
    else:
        raise Http404


def question(request):  # 题目详细，并显示提交
    assert isinstance(request, HttpRequest)

    if 'pid' in request.GET:
        p = Problem.objects.get(id=int(request.GET['pid']))
        is_login = request.user.is_authenticated
        if is_login:
            submissions = p.submission_set.filter(user=request.user)
            submission = None
            if (len(submissions) > 0):
                submission = submissions[0]
        else:
            submission = None
        return render(
            request,
            'app/problem.html',
            {
                'title': p.title,
                'p': p,
                'samples': json.loads(p.samples),
                'tags': p.tags.all(),
                'islogin': is_login,
                'submission': submission,
                'discusses': p.discuss_set.all(),
                'alltags': ProblemTag.objects.all(),
            }
        )
    else:
        raise Http404


@login_required(login_url='/login/')
def postdiscuss(request):  # 讨论
    assert isinstance(request, HttpRequest)
    if not request.user.is_authenticated:
        result = {"status": "err", "msg": "未登录"}
    else:
        if request.method == 'POST':
            form = DiscussForm(request.POST)
            if form.is_valid():
                cd = form.cleaned_data
                problem_id = int(cd['problem_id'])
                content = cd['content']

                s = Discuss()
                s.problem = Problem.objects.get(id=problem_id)
                s.user = request.user
                s.content = content
                s.create_time = datetime.now()
                s.save()

                result = {"status": "ok", "msg": "完成", 'data': s.id}
            else:
                result = {"status": "err", "msg": "检验错误"}
        else:
            result = {"status": "err", "msg": "程序出错"}
    return HttpResponse(json.dumps(result), content_type="application/json")


# 提交测试
@login_required(login_url='/login/')
def postsubmission(request):
    assert isinstance(request, HttpRequest)
    if not request.user.is_authenticated:
        result = {"status": "err", "msg": "未登录", 'data': None}
    else:
        if request.method == 'POST':
            form = SubmissionForm(request.POST)
            if form.is_valid():
                cd = form.cleaned_data
                problemid = int(cd['problem_id'])
                code = cd['code']

                s = Submission.objects.filter(user=request.user, problem_id=problemid).first()
                if s:
                    s.code = code
                    s.result = 0
                    s.info = ''
                    s.statistic_info = ''
                else:
                    s = Submission()
                    s.problem = Problem.objects.get(id=problemid)
                    s.user = request.user
                    s.code = code
                    s.result = JudgeStatus.PENDING
                    s.info = ''
                    s.statistic_info = ''
                    s.create_time = datetime.now()
                s.save()

                # 这里还需要创建任务，来进行评测
                # judge_task.send(s.id, problemid)
                # judge_task(s.id, problemid)

                result = {"status": "ok", "msg": "成功提交测试，请稍等即可看到结果。", 'data': s.id}
            else:
                result = {"status": "err", "msg": "检验错误"}
        else:
            result = {"status": "err", "msg": "程序出错"}
    return HttpResponse(json.dumps(result), content_type="application/json")


@login_required(login_url='/login/')
def getsubmission(request):
    submission_id = request.GET['id']
    if not submission_id:
        result = {"status": "err", "msg": "程序出错"}
    else:
        submission = Submission.objects.values('result', 'info', 'statistic_info').get(id=submission_id)
        result = {"status": "ok", "msg": "取得数据", 'data': submission}
    return HttpResponse(json.dumps(result), content_type="application/json")


@login_required(login_url='/login/')
def checktag(request):
    pid = request.GET['pid']
    tid = request.GET['tid']
    ac = request.GET['ac']
    if ac == 'add':
        sql = "INSERT INTO `problem_tags`(`problem_id`,`problemtag_id`) VALUES(%s, %s);" % (pid, tid)
    else:
        sql = "DELETE FROM `problem_tags` WHERE `problem_id`=%s AND `problemtag_id`=%s;" % (pid, tid)
    with connection.cursor() as cursor:
        cursor.execute(sql)

    result = {"status": "ok", "msg": "完成", 'data': {'id': tid, 'ac': ac}}
    return HttpResponse(json.dumps(result), content_type="application/json")


def getgroups(request):
    groups = Group.objects.values('id', 'name')
    result = {"status": "ok", "msg": "取得数据", 'data': list(groups)}
    return HttpResponse(json.dumps(result), content_type="application/json")


def getusersubmission(request):
    user_id = request.GET['id']
    u = User.objects.get(id=user_id)
    groups = u.groups.all()
    group = groups[0]
    hs = group.homework_set.all()
    works = []
    pids = []
    qc = 0;
    qac = 0;
    for h in hs:
        # 可以使用values来返回一下字典，包含指写的列，这样就用返回整个对象了，更省内存
        ps = h.special.problems.values("id", "title")
        works.append({'h': h.title, 'ps': list(ps)})
        for p in ps:
            pids.append(Problem(id=p['id']))

    ss = Submission.objects.filter(user=u, result=JudgeStatus.ACCEPTED, problem__in=pids).values("id", "result",
                                                                                                 "problem_id",
                                                                                                 "create_time")
    sdic = {}
    for s in ss:
        sdic[s["problem_id"]] = s;

    for w in works:
        for p in w['ps']:
            qc += 1
            if p['id'] in sdic:
                qac += 1
                p['submission'] = '完成'
            else:
                p['submission'] = '未完成'

    result = {"status": "ok", "msg": "取得数据", 'data': works}
    return HttpResponse(json.dumps(result), content_type="application/json")


def getusers(request):
    group_id = request.GET['id']
    us = User.objects.filter(groups__id=group_id).values('id', 'username', 'first_name').order_by('id')
    uids = []
    for u in us:
        uids.append(User(id=u['id']))
    ss = Submission.objects.filter(user__in=uids, result=JudgeStatus.ACCEPTED).values("user_id").order_by(
        'user_id').annotate(count=Count('user_id'))

    qid = 0
    fd = False
    for u in us:
        fd = False
        for i in range(qid, len(ss)):
            if ss[i]['user_id'] == u['id']:
                qid = i + 1
                fd = True
                u['accepted'] = ss[i]['count']
                break
        if not fd:
            u['accepted'] = 0

    result = {"status": "ok", "msg": "取得数据", 'data': list(us)}
    return HttpResponse(json.dumps(result), content_type="application/json")


